package com.leenmvc.core.init;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.leenmvc.core.dao.communal.dataEntity.DataSourceFactory;
import com.leenmvc.core.dao.communal.dataEntity.DataSourceGroup;
import com.leenmvc.core.dao.mysql.connect.DbConfig;
import com.leenmvc.core.dao.mysql.connect.DbConfigList;
import com.leenmvc.core.utils.collection.ArrayUtils;
import com.leenmvc.core.utils.datasource.DBUtil;
import com.leenmvc.core.utils.spring.Spring;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Order(10)
public class InitDb implements ApplicationRunner {

    private final static Logger logger = LoggerFactory.getLogger(InitDb.class);

    private static Map<String, DataSourceGroup> dsGroup = new HashMap<>();

    public static DataSourceGroup getDsGroup(String dataSourceGroupName) {
        return dsGroup.get(dataSourceGroupName);
    }

    public static Map<String, DataSourceGroup> getAllDsGroup() {
        return dsGroup;
    }

    @Override
    public void run(ApplicationArguments args) {
        File file = new File(Constant.WORK_DIR + "/database.json");
        ConfigurableListableBeanFactory beanFactory = Spring.APP.getBeanFactory();
        List<DbConfig> dbConfigs = beanFactory.getBean(DbConfigList.class).getC3p();
        OutputStream ops = null;
        InputStream ips = null;
        try {
            if (file.exists()) {
                ips = new FileInputStream(file);
                BufferedInputStream bis = new BufferedInputStream(ips);
                byte[] bytes = new byte[(int) file.length()];
                int len = 0;
                while ((len = bis.read(bytes)) != -1) {
                    String s = new String(bytes, 0, len);
                    dbConfigs = JSONArray.parseArray(s, DbConfig.class);
                }
                ips.close();
            } else {
                String dbStr = JSON.toJSONString(dbConfigs);
                file.createNewFile();
                ops = new FileOutputStream(file);
                ops.write(dbStr.getBytes());
                ops.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        dbConfigs.forEach(dbConfig -> {
            DataSourceFactory dataSourceFactory = DBUtil.createDataSource(beanFactory, dbConfig);
            InitDataSourceGroup(dbConfig, dataSourceFactory);
        });
    }

    /**
     * 初始化数据库连接组
     *
     * @param dbConfig
     * @param dataSourceFactory
     */
    private void InitDataSourceGroup(DbConfig dbConfig, DataSourceFactory dataSourceFactory) {
        DataSourceGroup dataSourceGroup = dsGroup.get(dbConfig.getDataSourceGroup());
        if (dataSourceGroup == null) {
            notExistDataSourceGroup(dbConfig, dataSourceFactory.getDataSource(), dataSourceFactory.getSqlSessionFactory());
        } else {
            existDataSourceGroup(dbConfig, dataSourceFactory.getDataSource(), dataSourceFactory.getSqlSessionFactory(), dataSourceGroup);
        }
    }

    /**
     * 如果不存在对应于groupname的 dataSourceGroup
     *
     * @param dbConfig
     * @param dataSource
     * @param dsBean
     */
    private void notExistDataSourceGroup(DbConfig dbConfig, DataSource dataSource, SqlSessionFactory dsBean) {
        DataSourceGroup dataSourceGroup;
        dataSourceGroup = new DataSourceGroup();
        dataSourceGroup.setGroupName(dbConfig.getDataSourceBeanName());
        DataSourceFactory dataSourceFactory = new DataSourceFactory(dataSource, dsBean);
        /**
         * 设置默认库
         */
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_DEFAULT_SUF)) {
            dataSourceGroup.setDefaultSource(dataSourceFactory);
        }

        /**
         * 设置信息库
         */
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_INFO_SUF)) {
            dataSourceGroup.setInformationSource(dataSourceFactory);
            dsGroup.put(dbConfig.getDataSourceGroup() + Constant.DATASOURCE_BEAN_INFO_SUF, dataSourceGroup);
        }
        /**
         * 读库初始化
         */
        DataSourceFactory[] readSources = new DataSourceFactory[0];
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_READ_SUF)) {
            readSources = ArrayUtils.arrayAdd(readSources, dataSourceFactory);
        }
        dataSourceGroup.setReadSources(readSources);

        /**
         * 写库初始化
         */
        DataSourceFactory[] writeSources = new DataSourceFactory[0];
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_WRITE_SUF)) {
            writeSources = ArrayUtils.arrayAdd(writeSources, dataSourceFactory);
        }
        dataSourceGroup.setWriteSources(writeSources);
        dataSourceGroup.putDataSourceFactory(dbConfig.getDataSourceBeanName(), dataSourceFactory);
        dsGroup.put(dbConfig.getDataSourceGroup(), dataSourceGroup);
    }

    /**
     * 如果存在对应于groupname的 dataSourceGroup
     *
     * @param dbConfig
     * @param dataSource
     * @param dsBean
     * @param dataSourceGroup
     */
    private void existDataSourceGroup(DbConfig dbConfig, DataSource dataSource, SqlSessionFactory dsBean, DataSourceGroup dataSourceGroup) {
        DataSourceFactory dataSourceFactory = new DataSourceFactory(dataSource, dsBean);
        /**
         * 设置默认库
         */
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_DEFAULT_SUF)) {
            dataSourceGroup.setDefaultSource(dataSourceFactory);
        }

        /**
         * 设置信息库
         *
         */
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_INFO_SUF)) {
            dataSourceGroup.setInformationSource(dataSourceFactory);
            dsGroup.put(dbConfig.getDataSourceGroup() + Constant.DATASOURCE_BEAN_INFO_SUF, dataSourceGroup);
        }
        /**
         * 读库初始化
         */
        DataSourceFactory[] readSources = dataSourceGroup.getReadSources();
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_READ_SUF)) {
            readSources = ArrayUtils.arrayAdd(readSources, dataSourceFactory);
        }
        dataSourceGroup.setReadSources(readSources);

        /**
         * 写库初始化
         */
        DataSourceFactory[] writeSources = dataSourceGroup.getWriteSources();
        if (dbConfig.getDataSourceBeanName().endsWith(Constant.DATASOURCE_BEAN_WRITE_SUF)) {
            writeSources = ArrayUtils.arrayAdd(writeSources, dataSourceFactory);
        }
        dataSourceGroup.setWriteSources(writeSources);
        dataSourceGroup.putDataSourceFactory(dbConfig.getDataSourceBeanName(), dataSourceFactory);
    }
}
